package com.design.pattern.strategy;

import com.design.pattern.strategy.enums.OptionServiceEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;

import javax.annotation.PostConstruct;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

public abstract class OptionalServiceProvider<T, S extends T>  implements BeanFactoryAware {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private ConfigurableListableBeanFactory beanFactory;

    /**
     * 服务实例map
     * key：业务流水号，value：对应的接口实现实例
     */
    private Map<String, T> serviceMap;

    @SuppressWarnings("unchecked")
    @PostConstruct
    public void init(){
        ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
        //getActualTypeArguments()返回表示此类型实际类型参数的 Type 对象的数组
        Type[] types = pt.getActualTypeArguments();

        Class<T> interfaceClazz = (Class<T>)types[0];
        Class<S> defaultImplClazz = (Class<S>)types[1];

        logger.info("可选服务初始化，服务接口为{}，默认实现为{}", interfaceClazz.getName(), defaultImplClazz.getName());

        Map<String, T> serviceBeanMap = beanFactory.getBeansOfType(interfaceClazz);
        serviceMap = new HashMap<String , T>(serviceBeanMap.size());

        for (T processor : serviceBeanMap.values()) {
            if (!(processor instanceof OptionalServiceSelector)) {
                // 如果实现类没有实现OptionalServiceSelector接口，则无法识别业务流水，报错
                throw new RuntimeException("可选服务必须实现OptionalServiceSelector接口！");
            }
            // 如果已经存在相同业务流水的服务，则抛出错误
            OptionalServiceSelector selector = (OptionalServiceSelector)processor;
            if (null != serviceMap.get(selector.getBussNumber())) {
                throw new RuntimeException("已经存在业务流水【" + selector.getBussNumber() + "】的服务");
            }

            serviceMap.put(selector.getBussNumber(), processor);
        }

    }

    /**
     * 获取默认的服务实例
     * @return
     */
    public T getService() {
        // 使用默认实现
        return serviceMap.get(OptionServiceEnum.DEFAULT.getCode());
    }

    /**
     * 根据传入的业务流水号获取服务
     * @return
     */
    public T getService(String bussNumber) {
        if (null != serviceMap.get(bussNumber)) {
            return serviceMap.get(bussNumber);
        }
        // 使用默认实现
        return serviceMap.get(OptionServiceEnum.DEFAULT.getCode());
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        if (beanFactory instanceof DefaultListableBeanFactory) {
            this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
        }
    }
}
